#include "proc.h"

int Socket(int domain, int type, int protocol)
{

    int sock;
    if ((sock = socket(domain, type, protocol)) == -1)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    return sock;
}


void Connect(int socket, const struct sockaddr *address,
           socklen_t address_len)
{
    int status;
    if ((status = connect(socket, address, address_len)) == -1)
    {
        perror("connect");
        exit(EXIT_FAILURE);
    }
 
}


in_addr_t Inet_addr(const char *cp)
{
    in_addr_t ip;

    if ((ip = inet_addr(cp)) == INADDR_NONE)
    {
        fprintf(stderr, "inet_pton: error\n");
        exit(EXIT_FAILURE);
    }

    return ip;
}


ssize_t Recv(int socket, void *buffer, size_t length, int flags)
{
    size_t read_bytes;
    if ((read_bytes = recv(socket, buffer, length, flags)) == -1)
    {
        perror("recv");
        // exit(EXIT_FAILURE);
    }

    return read_bytes;
}


ssize_t Send(int socket, const void *buffer, size_t length, int flags)
{
    size_t sent_bytes;
    if ((sent_bytes = send(socket, buffer, length, flags)) == -1)
    {
        perror("send");
    }

    return sent_bytes;
}


pid_t Fork(void)
{
    pid_t pid;

    pid = fork();
    if (pid == -1)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    return pid;
}


int Bind(int socket, const struct sockaddr *address,
           socklen_t address_len)
{
    int ret;
    if ((ret = bind(socket, address, address_len)) == -1)
    {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    return ret;
}


int Listen(int socket, int backlog)
{
    int ret;
    if ((ret = listen(socket, backlog)) == -1)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    return ret;
}


int Accept(int socket, struct sockaddr *restrict address,
   socklen_t *restrict address_len)
{
    int ret;
    if ((ret = accept(socket, address, address_len)) == -1)
    {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    return ret;
}


void Pselect(int nfds, fd_set *readfds, const struct timespec *timeout)
{
    if (pselect(nfds, readfds, NULL, NULL, timeout, NULL) == -1)
    {
        perror("select");
        exit(EXIT_FAILURE);
    }
}


struct timespec timespec_subtract(struct timespec start, struct timespec end) {
    struct timespec result;

    if ((end.tv_nsec - start.tv_nsec) < 0) {
        result.tv_sec = end.tv_sec - start.tv_sec - 1;
        result.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
    } else {
        result.tv_sec = end.tv_sec - start.tv_sec;
        result.tv_nsec = end.tv_nsec - start.tv_nsec;
    }

    return result;
}
